(function( window ){
  function TabChange(opts){
    this.changing = false;
    this.tabs = $(opts.tabs) || null;
    this.index = null;
    this.btn = $(opts.btn) || null;
    this.length = this.tabs.length;
    // this.tabActiveString = $(opts.tabActiveString) || 'tabActive';
    // this.btnActiveString = $(opts.btnActiveString) || 'btnActive';
    // this.eleActiveString = $(opts.eleActiveString) || 'eleActive';
    // this.eleInterval = $(opts.eleInterval) || 50;
    this.tabActiveString = 'active';
    this.btnActiveString = 'active';
    this.eleActiveString = 'show';
    this.autoInit = false;
    this.eleInterval = 50;
  }

  TabChange.prototype = {
    constructor: TabChange,
    init: function(){
      var that = this;
      if (!that.tabs) {
        console.warn('tabs can not be null');
        return false;
      }
      // 自动初始化
      if(that.autoInit){
        that.showPage(0)
        that.btn.on('click', function(){
          var index = $(this).index();
          that.showPage(index)
        })
      }
    },
    showPage: function(index){
      var that = this;
      if (this.changing || this.index === index) {
        return false
      }
      this.changing = true;
      if (index > this.length) {
        index = 0
      }
      // 更新轮换点
      this.btn.removeClass(that.btnActiveString)
      this.btn.eq(index).addClass(that.btnActiveString)
      // 所有的内容更新完成之后，更新pageChanging
      // 显示内部元素
      if(this.index === null) {
        // 首次加载
        this.tabs.removeClass(that.tabActiveString);
        this.tabs.eq(index).addClass(that.tabActiveString);
        this.showEle(index, function(){
          that.index = index;
          that.changing = false;
        });
        return true;
      }
      this.hideEle(that.index, function(){
        that.tabs.removeClass(that.tabActiveString);
        that.tabs.eq(index).addClass(that.tabActiveString);
        // 显示延迟
        setTimeout(function(){
          that.showEle(index, function(){
            that.index = index;
            that.changing = false;
          });
        }, 200);
      });
    },
    showEle: function(index, callback){
      var that = this;
      var ele = this.tabs.eq(index).find('.container>.ele');
      if(!ele[0]){
        callback();
      }
      for(i = 0; i < ele.length; i++) {
        var obj = ele.eq(i);
        (function(i, obj, callback){
          setTimeout(function(){
            obj.addClass(that.eleActiveString);
            if(i === ele.length - 1){
              callback();
            }
            console.log(that.eleInterval * i)
          }, that.eleInterval * i)
        })(i, obj, callback)
      }
    },
    hideEle: function(index, callback){
      var that = this;
      var ele = this.tabs.eq(index).find('.container>.ele');
      if(!ele[0]){
        callback();
      }
      for(i = 0; i < ele.length; i++) {
        var obj = ele.eq(i);
        (function(i, obj, callback){
          setTimeout(function(){
            obj.removeClass(that.eleActiveString);
            if(i === ele.length - 1){
              callback();
            }
          }, that.veleInterval * i)
        })(i, obj, callback)
      }
    }
  }

  window.TabChange = TabChange;

})( window );


/**
 * Created by Hansn cz P03 on 2017/7/1.
 * Author : leohowl
 */
(function ( window){
  function EasyLightBox ( opts ){
    this.wrap = $(opts.wrap) || null;
    this.plate = this.wrap.find(opts.plate) || null;
    this.plateNum = this.plate.length;
    this.widthArray = [];
    this.speed = opts.speed || 500;
    this.interval = opts.interval || 5000;
    /**
     *
     * @type {number} plate之间的间隔，这个间隔是固定的
     */
    this.plateInterval = opts.plateInterval || 0;
    /**
     *
     * @type {*} 起始位置的调整
     */
    this.beginAdjustment = opts.firstAdjustment || 0;
    /**
     *
     * @type {string} mode 使用模式，auto自动模式，click点击模式，passive被动模式
     */
    this.mode = opts.mode || "auto";
    /**
     *
     * @type {object} control 被动模式下的控制机
     */
    this.control = opts.control || null;
    /**
     *
     * @type {number} curIndex 当前的index
     */
    this.curIndex = 0;//index of current image
    /**
     *
     * @type {number} targetIndex 目标index
     */
    this.targetIndex = 0;
    /**
     *
     * @type {boolean} actionAble 运行标志位
     */
    this.actionAble = true;
    /**
     *
     * @type {null} 自动播放时的定时器
     */
    this.t_autoClick = '';
    /**
     *
     * @type {boolean} autoAdd 初始化的时候是否对过少的plate进行复制
     */
    this.autoAdd = opts.autoAdd || true;
    /**
     *
     * @type {string} easing 缓动效果
     */
    this.easing = opts.easing || 'linear';
    /**
     *
     * @type {string} hoverStop 鼠标悬停时是否停止运动
     */
    this.hoverStop = opts.hoverStop || 'false';
    this.beforeActionCallback = opts.beforeActionCallback || function(){};
    this.afterActionCallback = opts.afterActionCallback || function(){};
    this.delayBefore = opts.delayBefore || 0;
    this.delayAfter = opts.delayAfter || 0;
    this.leftArrow = opts.leftArrow || false;
    this.rightArrow = opts.rightArrow || false;
    this.arrow = !!(opts.leftArrow && opts.rightArrow);
    //开始初始化
    this.init(opts);
  }

  EasyLightBox.prototype = {
    constructor : EasyLightBox,

    init : function(opts) {
      //确定plate是否存在
      if(!this.plate){
        return false;
      }
      //读取各plate的宽度
      var totleWidth = 0;
      for(var i = 0; i < this.plateNum; i++){
        var plateWidth = 0;
        plateWidth = this.plate.eq(i).width();
        this.widthArray.push(plateWidth);
        totleWidth = totleWidth + plateWidth + this.plateInterval;
      }

      //plate补齐
      if(totleWidth < (this.wrap.width() + Math.max.apply(null,this.widthArray))){
        //如果所有模块的宽度，间距和小于容器的宽度则确定是不是要自动增加plate的数量,要加上plate最大的宽度
        if(this.autoAdd){
          //自动增加plate的初始化方法已经打开
          this.addPlate(totleWidth, this.wrap.width() + Math.max.apply(null,this.widthArray),opts);
        }
      }
      //样式调整
      this.cssAdjustment();
    },

    /**
     * @type {function} 对plate的数量进行补齐
     */
    addPlate : function(totleWidth, wrapWidth, opts){
      //对plate的原始的plate进行标记
      for(var i = 0; i < this.plateNum; i++){
        this.plate.eq(i).attr("LightBoxIndex",i);
      }
      //计算补齐倍数
      var time = Math.ceil(wrapWidth/totleWidth);

      var wrap = this.wrap.html();

      var widthArray1 = this.widthArray;
      for(var i = 0; i < time - 1; i++){
        this.wrap.append(wrap);

      }
      //重置参数
      this.plate = this.wrap.find(opts.plate);
      this.plateNum = this.plate.length;
      this.wrapWidth = this.resetWidthArray();
    },

    resetWidthArray : function(){
      this.widthArray.length = 0;
      for(var i = 0; i < this.plateNum; i++){
        plateWidth = this.plate.eq(i).width();
        this.widthArray.push(plateWidth);
      }
    },

    cssAdjustment : function(){
      //容器样式
      this.wrap.css({
        position:'relative',
        overflow:"hidden"
      });
      //plate样式
      var left = this.beginAdjustment;
      for(var i = 0; i < this.plate.length; i++){
        var obj = this.plate.eq(i);
        obj.css({
          left:left,
          position:'absolute',
          top:0
        });
        left = left + obj.width()+ this.plateInterval;
      }
      //当左右按钮已经赋值，且不是passive模式的时候绑定按钮
      if(this.arrow && this.mode !== 'passive'){
        var that = this;
        //上一张
        $(document).on('click',this.leftArrow,function(){
          that.prev();
        });
        $(document).on('click',this.rightArrow,function(){
          that.next();
        });
      }
      //鼠标悬停绑定
      if(this.hoverStop){
        var that = this;
        //鼠标悬停
        $(that.wrap).on('mouseenter',function(){
          if(that.t_autoClick){
            clearTimeout(that.t_autoClick);
          }
        });
        //鼠标取消悬停
        $(that.wrap).on('mouseleave',function(){
          if(that.mode === 'auto'){
            that.t_autoClick = setTimeout(function(){that.next();},that.interval);
          }
        });
      }
      //初始化当前左侧显示的第一张的index
      this.curIndex = 0;
      //是否开始自动化播放
      if(this.mode === 'auto' && this.autoStart){
        //当前为自动；轮播模式, 且自动启动
        var that = this;
        this.t_autoClick = setTimeout(function(){that.next();},that.interval);
      }
    },

    prev : function(){
      if(this.mode === 'passive'){
        return false;
      }
      var targetIndex = (this.plateNum + this.curIndex - 1) % this.plateNum;
      this.plateAnimate(targetIndex,'prev');
    },
    next : function(){
      if(this.mode === 'passive'){
        return false;
      }
      var targetIndex = (this.curIndex + 1) % this.plateNum;
      this.plateAnimate(targetIndex,'next');
    },
    jump : function(type,targetIndex){
      if(type === 'control' && this.mode !== 'passive'){
        //表示当前为控制机操作，若没有启用被动模式则不执行，控制机误操作防止
        return;
      }
      this.plateAnimate(targetIndex,'next');
    },

    plateAnimate : function(targetIndex,arrowType){
      //如果正在运行则忽略这个请求
      if(!this.actionAble){
        return false;
      }
      //活动图片验证
      if(targetIndex === this.curIndex){
        return false;
      }
      //开始处理请求
      this.targetIndex = targetIndex;
      //运行标志位置为false，屏蔽接下来的请求
      this.actionAble = false;
      //清除自动播放定时器
      if(this.t_autoClick){
        clearTimeout(this.t_autoClick);
      }
      //如果开启控制模式，这可以控制其他轮播
      if(this.control){
        var i;
        for(i = 0; i < this.control.length; i++){
          var run = function(i){
            var obj = eb.control[i].object;
            var delay = eb.control[i].delay;
            var t_mode = setTimeout(function(){obj.jump('control',targetIndex);},delay);//control 表示是由控制机控制
          };
          run(i);
        }
      }
      //执行前执行回调函数
      this.callback(this.beforeActionCallback, this.delayBefore);
      //开始执行动画
      this.animateAction(arrowType);

    },
    animateAction : function(arrowType){
      var target = this.targetIndex;
      var that = this;

      if(arrowType === 'prev'){
        //上一张
        var plate = this.plate.eq(target);
        //先将末尾plate转移至头部
        plate.css({
          left:-(plate.width()+that.plateInterval-that.beginAdjustment)
        });
        this.plate.animate({
          left:'+='+(plate.width()+that.plateInterval)
        },that.speed,that.easing,function(){
          //设置标志位
          that.actionAble = true;
          //设置plate指针
          that.curIndex = target;
          //执行回调
          that.callback(that.afterActionCallback,that.delayAfter);
          //如果当前的模式为auto,设置定时器
          if(that.mode === 'auto'){
            that.t_autoClick = setTimeout(function(){
              that.next();
            },that.interval);
          }
        });
      } else if(arrowType === 'next') {
        //下一张
        //回调计数器
        var loopflag = 0;
        var plate = this.plate.eq(this.curIndex);
        this.plate.animate({
          left:'-='+(plate.width()+that.plateInterval)
        },that.speed,that.easing,function(){
          loopflag++;
          if(loopflag >= that.widthArray.length){
            //调整位置
            //计算plate长度之和
            var totalWidth = 0;
            for(var i = 0; i < that.widthArray.length; i++){
              totalWidth = totalWidth + that.widthArray[i] + that.plateInterval;
            }
            that.plate.eq(that.curIndex).css({
              left : totalWidth - that.widthArray[that.curIndex] - that.plateInterval + that.beginAdjustment
            });
            //设置标志位
            that.actionAble = true;
            //设置plate指针
            that.curIndex = target;
            //执行回调
            that.callback(that.afterActionCallback,that.delayAfter);
            //如果当前的模式为auto,设置定时器
            if(that.mode === 'auto'){
              that.t_autoClick = setTimeout(function(){
                that.next();
              },that.interval);
            }
          }
        });

      }
    },
    callback : function(c,delay){
      delay = delay || 0;
      if( typeof c === 'function'){
        var t_callback = setTimeout(function () {
          c();
        },delay);
      }
    }
  };

  window.EasyLightBox = EasyLightBox;
  window.ELB = EasyLightBox;
})( window );


/*!
 * EasyBanner
 *
 * Date: 2016-12-5
 * Author: leohowl
 */

(function( window ){
  // var EasyBanner = window.EasyBanner;

  function EasyBanner(opts){
    /**
     *
     * @param {viewWidth} 浏览器有效宽度
     */
    this.viewWidth = $(window).width();

    /**
     *
     * @param {viewHeight} 浏览器有效高度
     */
    this.viewHeight = $(window).height();

    /**
     *
     * @param {wrap} 父级容器
     */
    this.wrap = $(opts.wrap) ||  null;

    /**
     *
     * @param {img} 子元素
     * 子元素将从父级容器中查找，不必重复父级容器的选择器
     *
     */
    this.img = this.wrap.find(opts.img) || null;

    /**
     * @param {imgNum} 子元素的图片
     * 自动生成，无需手动添加
     */
    this.imgNum = this.img.length;

    /**
     *
     * @param {speed} 子元素切换速度
     */
    this.speed  = opts.speed || 1000;

    /**
     *
     * @param {interval} 子元素切换间隔
     */
    this.interval = (opts.interval > this.speed + 500) ? opts.interval : 2000;

    /**
     *
     * @param {mode} 切换模式
     * 包括"auto","click","passive"
     * auto模式下将自动切换
     * click模式下，需要通过点击“焦点”或“上一张，下一张”按钮切换
     * passive模式下，只能被其他实例控制
     */
    this.mode = opts.mode || 'auto';

    this.autoStart = opts.autoStart || false;

    /**
     *
     * @param {control} 控制模式
     * 实例开启此项时，将被作为控制机使用，控制其他mode为passive的实例
     */
    this.control = opts.control || null;

    /**
     *
     * @param {method} 切换风格
     * fade为渐入渐出
     * slide为滑动
     */
    this.method = opts.method || 'fade';

    /**
     *
     * @param {direction} 切换方向
     * 此项为method为“slide”的进一步配置，用于设置滑动方向
     */
    this.direction = opts.direction || 'right';

    /**
     *
     * @param {displacement} slide切换的相对位移，取值范围为[0,1]
     */
    this.displacement = opts.displacement || 0;

    /**
     *
     * @param {preImg} 上一个显示的元素的index
     */
    this.preImg = 0;

    /**
     *
     * @param {curImg} 当前显示的元素的index
     */
    this.curImg = 0;

    /**
     *
     * @param {targetIndex} 目标显示的元素的index
     */
    this.targetIndex = 0;

    /**
     *
     * @param {actionAble} 切换保护
     */
    this.actionAble = true;

    /**
     *
     * @param {wrapWidth} 父级容器宽度
     */
    this.wrapWidth = this.wrap.width();

    /**
     *
     * @param {wrapHeight} 父级容器高度
     */
    this.wrapHeight = this.wrap.height();

    /**
     *
     * @param {easing} 缓动效果
     */
    this.easing = opts.easing || '';

    /**
     *
     * @param {initLeft} 子元素初始化位置信息
     */
    this.initLeft = 0;

    /**
     *
     * @param {initLeft} 子元素初始化位置信息
     */
    this.initTop = 0;

    /**
     *
     * @param {timer_autoClick} 自动轮播定时器
     */
    this.timer_autoClick = null;

    /**
     *
     * @param {beforeActionCallback} 子元素切换前回调函数
     */
    this.beforeActionCallback = opts.beforeActionCallback || function(){};

    /**
     *
     * @param {afterActionCallback} 子元素切换后回调函数
     */
    this.afterActionCallback = opts.afterActionCallback || function(){};

    /**
     *
     * @param {delayBefore} 子元素切换前回调函数的执行延时
     */
    this.delayBefore = opts.delayBefore || 0;

    /**
     *
     * @param {delayAfter} 子元素切换后回调函数的执行延时
     */
    this.delayAfter = opts.delayAfter || 0;

    /**
     *
     * @param {leftArrow} ”上一张“切换按钮
     */
    this.leftArrow = opts.leftArrow || false;

    /**
     *
     * @param {rightArrow} ”下一张“切换按钮
     */
    this.rightArrow = opts.rightArrow || false;

    /**
     *
     * @param {arrow} 切换按钮设置完全验证
     */
    this.arrow = !!(opts.leftArrow && opts.rightArrow);

    /**
     *
     * @param {btn} 切换焦点
     */
    this.btn = opts.btn || false;
    // this.smallImg = opts.smallImg || false;
    // this.timeLine = opts.timeLine || false;
    //杂项
    // this.waterMark = opts.waterMark || false;
    this.init();//initialize

  }

  EasyBanner.prototype = {
    constructor : EasyBanner,

    init : function(){
      //show Author
      if(this.waterMark){
        // this.showDesign();
      }
      //normal init
      this.wrap.css({
        position: 'relative',
        overflow: 'hidden'
      });
      this.img.css({//default init
        position : 'absolute',
        left: 0,
        top: 0
      });
      this.img.removeClass('EasyBannerActive');
      this.img.eq(0).addClass('EasyBannerActive');
      //移动端时间初始化
      //special init
      switch(this.method){
        case "fade":
          this.img.hide();
          this.img.eq(0).show();
          break;
        case "slide":
          //also execute with $(window).resize
          this.slidePositionInit();
          break;
        default:
          break;
      }
      //bind
      var eb = this;
      $(window).resize(function(event) {
        eb.wrapWidth = eb.wrap.width();
        eb.wrapHeight = eb.wrap.height();
        //slide position init
        eb.slidePositionInit();
      });
      //扩展初始化
      this.pluginInit();
      if(this.mode === 'auto' && this.autoStart){
        //当前为自动；轮播模式
        this.timer_autoClick = setTimeout(function(){eb.next();},this.interval);
      }

    },
    slidePositionInit : function(){
      //set origin position
      if(this.method !== 'slide'){
        return false;
      }
      switch(this.direction){
        case "right":
          this.initLeft = this.wrapWidth;
          this.initTop = 0;
          break;
        case "left":
          this.initLeft = -this.wrapWidth;
          this.initTop = 0;
          break;
        case "top":
          this.initLeft = 0;
          this.initTop = -this.wrapHeight;
          break;
        case "bottom":
          this.initLeft = 0;
          this.initTop = this.wrapHeight;
          break;
      }
      var eb = this;
      this.img.each(function(index, el) {
        $(this).css({
          left: eb.initLeft+'px',
          top: eb.initTop+'px',
          'z-index' : 101,
          display: 'block'
        });
      });
      //初次位置初始化检查
      var activeIndex = 0;
      this.img.each(function(index, el) {
        if($(this).hasClass('EasyBannerActive')){
          activeIndex = index;
          return null;
        }
      });
      // console.log(activeIndex);
      this.img.eq(activeIndex).css({
        'z-index': 100,
        left: 0,
        top: 0
      });
    },
    pluginInit : function(){
      /**
       * 焦点初始化，在被动模式下，不会初始化翻页，不会为按钮绑定点击事件
       * @type {EasyBanner}
       */
      var eb = this;
      if(this.btn){
        $(this.btn).removeClass('EasyBannerBtnActive');
        $(this.btn).eq(0).addClass('EasyBannerBtnActive');
        //如果不是被动模式则为按钮绑定点击事件
        if(this.mode !== "passive"){
          $(this.btn).on('click',function(){
            var index = $(this).index();
            eb.jump(index,'click');
          });
        }
      }
      //翻页按钮初始化
      if(this.arrow && this.mode !== 'passive'){
        //
        $(this.leftArrow).on('click',function(){
          //翻页，上一张
          eb.prev();
        });
        $(this.rightArrow).on('click',function(){
          //翻页，下一张
          eb.next();
        })
      }
    },
    action : function(targetIndex){
      var currentIndex = this.curImg;
      //设置banner的active
      this.img.removeClass('EasyBannerActive');
      this.img.eq(targetIndex).addClass('EasyBannerActive');
      switch (this.method){
        case "fade":
          fade(this);
          break;
        case "slide":
          slide(this);
          break;
      }
      if(this.mode === 'auto'){
        //如果当前为自动模式，则自动切换
        var eb = this;
        this.timer_autoClick = setTimeout(function(){eb.next();},this.interval);
      }

      var i = 1;
      function fade(eb){
        eb.img.eq(eb.curImg).fadeOut(eb.speed);
        eb.img.eq(targetIndex).fadeIn(eb.speed,function(){
          //自定义回调函数
          eb.callback(eb.afterActionCallback,eb.delayAfter);
          //调用插件
          var pluginOpts = {
            type : 'after',
            targetIndex : targetIndex
          };
          eb.plugin(pluginOpts);
          //设置请求标志位允许
          eb.actionAble = true;
          //动画完成，设置图片指针
          eb.preImg = eb.curImg;
          eb.curImg = targetIndex;
        });

      }
      function slide(eb){
        eb.img.eq(eb.curImg).css('z-index', '100');
        eb.img.eq(eb.curImg).animate({
          left: -eb.initLeft*eb.displacement,
          top: -eb.initTop*eb.displacement
        },eb.speed,eb.easing,function(){
          //退场图片样式
          $(this).css({
            left: eb.initLeft,
            top: eb.initTop,
            'z-index':101
          });
          //自定义回调函数
          eb.callback(eb.afterActionCallback,eb.delayAfter);
          //调用插件
          var pluginOpts = {
            type : 'after',
            targetIndex : targetIndex
          };
          eb.plugin(pluginOpts);
          //设置请求标志位允许
          eb.actionAble = true;
          //动画完成，设置图片指针
          eb.preImg = eb.curImg;
          eb.curImg = targetIndex;
        });
        eb.img.eq(targetIndex).animate({
          left: 0,
          top: 0}, eb.speed, eb.easing);
      }
    },
    changeAction : function(opts){
      //
      var eb = this;
      //响应请求
      if(!this.actionAble){
        return;
      }
      //参数处理
      var targetIndex = opts.targetIndex;

      //若目标图片为当前图片，则忽略
      if(this.curImg === targetIndex){
        return;
      }

      //暴露切换的目标图片，方便外部引用
      this.targetIndex = targetIndex;

      //设置请求标志位为不允许
      this.actionAble = false;

      //清除开始进行轮播后产生定时器
      if(this.timer_autoClick){ clearTimeout(this.timer_autoClick); }

      //如果开启控制模式，这可以控制其他轮播
      if(this.control){
        var i;
        for(i = 0; i < this.control.length; i++){
          var run = function(i){
            var obj = eb.control[i].object;
            var delay = eb.control[i].delay;
            var t_mode = setTimeout(function(){obj.jump(targetIndex,'control');},delay);//control 表示是由控制机控制
          };
          run(i);
        }
      }
      //执行前执行回调函数
      this.callback(this.beforeActionCallback, this.delayBefore);
      //调用插件
      var pluginOpts = {
        type : 'before',
        targetIndex : targetIndex
      };
      this.plugin(pluginOpts);
      //选择动作方法
      switch (this.method){
        case 'fade':
          this.action(targetIndex);
          break;
        case 'slide':
          this.action(targetIndex);
      }
    },

    /**
     * 下一张，使当前的curImg增加1，然后调用图片切换
     */
    next : function(){
      //被动模式中，亦不可通过调用方法翻页
      if(this.mode !== 'passive'){
        this.changeAction({
          targetIndex : (this.curImg + 1) % this.imgNum
        });
      }

    },
    /**
     * 上一张，使当前的curImg减少1，然后调用图片切换
     */
    prev : function(){
      if(this.mode !== 'passive'){
        this.changeAction({
          targetIndex : (this.curImg - 1 + this.imgNum) % this.imgNum
        });
      }
    },

    /**
     *
     * @param index 切换的目标图片
     * @param type 当前控制模式
     */
    jump : function(index,type){
      //type的类型：click来自鼠标点击，control来自控制机。
      if(type === 'control' && this.mode !== 'passive'){
        //表示当前为控制机操作，若没有启用被动模式则不执行，控制机误操作防止
        return;
      }
      this.changeAction({
        targetIndex : index
      });
    },
    plugin : function(opts){
      if(opts.type === 'before'){
        if(this.btn){
          //btn设置
          $(this.btn).removeClass('EasyBannerBtnActive');
          $(this.btn).eq(opts.targetIndex).addClass('EasyBannerBtnActive');
        }
      }
      if(opts.type === 'after'){

      }
    },
    callback : function(c,delay){
      delay = delay || 0;
      if( typeof c === 'function'){
        var t_callback = setTimeout(function () {
          c();
        },delay);
        // console.log("callback");
      }
    }
  };
  window.EB = EasyBanner;
  window.EasyBanner = window.EB;
})(window);

(function( window ){

  //将改方法注册到window中
  var url;
  window.getUrl = function(o) {
    if(!o || o==='#' )
    {
      //按照“#”来解析
      url = location.hash;
      if (url.indexOf("#") !== -1)
      {
        url = url.substr(1);
      } else {
        return null;
      }
    } else if(o==='?') {
      //按照“？”来解析
      url = location.search;
      if (url.indexOf("?") !== -1)
      {
        url = url.substr(1);
      } else {
        return null;
      }
    } else {
      return null;
    }
    var p2 = /=/gi;
    if(p2.test(url))
    {
      //存在等于号
      var theRequest = new Object();
      strs = url.split("&");//拆分变量
      for(var i = 0; i < strs.length; i ++) {
        theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);//拆分变量名和值
      }
      return theRequest;
    }
    return url;
  };
  window.sectionJump = function(){
    var tag = getUrl('#');
    // console.log(tag)
    var target = $('span[name="'+tag+'"]');
    if(target[0]){
      $('html,body').animate({
        scrollTop:target.offset().top
      },500);
    }
  }
})(window);


//---------------------------------------------------------------------
// QRCode for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
//   http://www.opensource.org/licenses/mit-license.php
//
// The word "QR Code" is registered trademark of
// DENSO WAVE INCORPORATED
//   http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------

//---------------------------------------------------------------------
// QR8bitByte
//---------------------------------------------------------------------

function QR8bitByte(data) {
  this.mode = QRMode.MODE_8BIT_BYTE;
  this.data = data;
}

QR8bitByte.prototype = {

  getLength : function(buffer) {
    return this.data.length;
  },

  write : function(buffer) {
    for (var i = 0; i < this.data.length; i++) {
      // not JIS ...
      buffer.put(this.data.charCodeAt(i), 8);
    }
  }
};

//---------------------------------------------------------------------
// QRCode
//---------------------------------------------------------------------

function QRCode(typeNumber, errorCorrectLevel) {
  this.typeNumber = typeNumber;
  this.errorCorrectLevel = errorCorrectLevel;
  this.modules = null;
  this.moduleCount = 0;
  this.dataCache = null;
  this.dataList = new Array();
}

QRCode.prototype = {

  addData : function(data) {
    var newData = new QR8bitByte(data);
    this.dataList.push(newData);
    this.dataCache = null;
  },

  isDark : function(row, col) {
    if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
      throw new Error(row + "," + col);
    }
    return this.modules[row][col];
  },

  getModuleCount : function() {
    return this.moduleCount;
  },

  make : function() {
    // Calculate automatically typeNumber if provided is < 1
    if (this.typeNumber < 1 ){
      var typeNumber = 1;
      for (typeNumber = 1; typeNumber < 40; typeNumber++) {
        var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel);

        var buffer = new QRBitBuffer();
        var totalDataCount = 0;
        for (var i = 0; i < rsBlocks.length; i++) {
          totalDataCount += rsBlocks[i].dataCount;
        }

        for (var i = 0; i < this.dataList.length; i++) {
          var data = this.dataList[i];
          buffer.put(data.mode, 4);
          buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) );
          data.write(buffer);
        }
        if (buffer.getLengthInBits() <= totalDataCount * 8)
          break;
      }
      this.typeNumber = typeNumber;
    }
    this.makeImpl(false, this.getBestMaskPattern() );
  },

  makeImpl : function(test, maskPattern) {

    this.moduleCount = this.typeNumber * 4 + 17;
    this.modules = new Array(this.moduleCount);

    for (var row = 0; row < this.moduleCount; row++) {

      this.modules[row] = new Array(this.moduleCount);

      for (var col = 0; col < this.moduleCount; col++) {
        this.modules[row][col] = null;//(col + row) % 3;
      }
    }

    this.setupPositionProbePattern(0, 0);
    this.setupPositionProbePattern(this.moduleCount - 7, 0);
    this.setupPositionProbePattern(0, this.moduleCount - 7);
    this.setupPositionAdjustPattern();
    this.setupTimingPattern();
    this.setupTypeInfo(test, maskPattern);

    if (this.typeNumber >= 7) {
      this.setupTypeNumber(test);
    }

    if (this.dataCache == null) {
      this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
    }

    this.mapData(this.dataCache, maskPattern);
  },

  setupPositionProbePattern : function(row, col)  {

    for (var r = -1; r <= 7; r++) {

      if (row + r <= -1 || this.moduleCount <= row + r) continue;

      for (var c = -1; c <= 7; c++) {

        if (col + c <= -1 || this.moduleCount <= col + c) continue;

        if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
          || (0 <= c && c <= 6 && (r == 0 || r == 6) )
          || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
          this.modules[row + r][col + c] = true;
        } else {
          this.modules[row + r][col + c] = false;
        }
      }
    }
  },

  getBestMaskPattern : function() {

    var minLostPoint = 0;
    var pattern = 0;

    for (var i = 0; i < 8; i++) {

      this.makeImpl(true, i);

      var lostPoint = QRUtil.getLostPoint(this);

      if (i == 0 || minLostPoint >  lostPoint) {
        minLostPoint = lostPoint;
        pattern = i;
      }
    }

    return pattern;
  },

  createMovieClip : function(target_mc, instance_name, depth) {

    var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
    var cs = 1;

    this.make();

    for (var row = 0; row < this.modules.length; row++) {

      var y = row * cs;

      for (var col = 0; col < this.modules[row].length; col++) {

        var x = col * cs;
        var dark = this.modules[row][col];

        if (dark) {
          qr_mc.beginFill(0, 100);
          qr_mc.moveTo(x, y);
          qr_mc.lineTo(x + cs, y);
          qr_mc.lineTo(x + cs, y + cs);
          qr_mc.lineTo(x, y + cs);
          qr_mc.endFill();
        }
      }
    }

    return qr_mc;
  },

  setupTimingPattern : function() {

    for (var r = 8; r < this.moduleCount - 8; r++) {
      if (this.modules[r][6] != null) {
        continue;
      }
      this.modules[r][6] = (r % 2 == 0);
    }

    for (var c = 8; c < this.moduleCount - 8; c++) {
      if (this.modules[6][c] != null) {
        continue;
      }
      this.modules[6][c] = (c % 2 == 0);
    }
  },

  setupPositionAdjustPattern : function() {

    var pos = QRUtil.getPatternPosition(this.typeNumber);

    for (var i = 0; i < pos.length; i++) {

      for (var j = 0; j < pos.length; j++) {

        var row = pos[i];
        var col = pos[j];

        if (this.modules[row][col] != null) {
          continue;
        }

        for (var r = -2; r <= 2; r++) {

          for (var c = -2; c <= 2; c++) {

            if (r == -2 || r == 2 || c == -2 || c == 2
              || (r == 0 && c == 0) ) {
              this.modules[row + r][col + c] = true;
            } else {
              this.modules[row + r][col + c] = false;
            }
          }
        }
      }
    }
  },

  setupTypeNumber : function(test) {

    var bits = QRUtil.getBCHTypeNumber(this.typeNumber);

    for (var i = 0; i < 18; i++) {
      var mod = (!test && ( (bits >> i) & 1) == 1);
      this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
    }

    for (var i = 0; i < 18; i++) {
      var mod = (!test && ( (bits >> i) & 1) == 1);
      this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
    }
  },

  setupTypeInfo : function(test, maskPattern) {

    var data = (this.errorCorrectLevel << 3) | maskPattern;
    var bits = QRUtil.getBCHTypeInfo(data);

    // vertical
    for (var i = 0; i < 15; i++) {

      var mod = (!test && ( (bits >> i) & 1) == 1);

      if (i < 6) {
        this.modules[i][8] = mod;
      } else if (i < 8) {
        this.modules[i + 1][8] = mod;
      } else {
        this.modules[this.moduleCount - 15 + i][8] = mod;
      }
    }

    // horizontal
    for (var i = 0; i < 15; i++) {

      var mod = (!test && ( (bits >> i) & 1) == 1);

      if (i < 8) {
        this.modules[8][this.moduleCount - i - 1] = mod;
      } else if (i < 9) {
        this.modules[8][15 - i - 1 + 1] = mod;
      } else {
        this.modules[8][15 - i - 1] = mod;
      }
    }

    // fixed module
    this.modules[this.moduleCount - 8][8] = (!test);

  },

  mapData : function(data, maskPattern) {

    var inc = -1;
    var row = this.moduleCount - 1;
    var bitIndex = 7;
    var byteIndex = 0;

    for (var col = this.moduleCount - 1; col > 0; col -= 2) {

      if (col == 6) col--;

      while (true) {

        for (var c = 0; c < 2; c++) {

          if (this.modules[row][col - c] == null) {

            var dark = false;

            if (byteIndex < data.length) {
              dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
            }

            var mask = QRUtil.getMask(maskPattern, row, col - c);

            if (mask) {
              dark = !dark;
            }

            this.modules[row][col - c] = dark;
            bitIndex--;

            if (bitIndex == -1) {
              byteIndex++;
              bitIndex = 7;
            }
          }
        }

        row += inc;

        if (row < 0 || this.moduleCount <= row) {
          row -= inc;
          inc = -inc;
          break;
        }
      }
    }

  }

};

QRCode.PAD0 = 0xEC;
QRCode.PAD1 = 0x11;

QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) {

  var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);

  var buffer = new QRBitBuffer();

  for (var i = 0; i < dataList.length; i++) {
    var data = dataList[i];
    buffer.put(data.mode, 4);
    buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) );
    data.write(buffer);
  }

  // calc num max data.
  var totalDataCount = 0;
  for (var i = 0; i < rsBlocks.length; i++) {
    totalDataCount += rsBlocks[i].dataCount;
  }

  if (buffer.getLengthInBits() > totalDataCount * 8) {
    throw new Error("code length overflow. ("
      + buffer.getLengthInBits()
      + ">"
      +  totalDataCount * 8
      + ")");
  }

  // end code
  if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
    buffer.put(0, 4);
  }

  // padding
  while (buffer.getLengthInBits() % 8 != 0) {
    buffer.putBit(false);
  }

  // padding
  while (true) {

    if (buffer.getLengthInBits() >= totalDataCount * 8) {
      break;
    }
    buffer.put(QRCode.PAD0, 8);

    if (buffer.getLengthInBits() >= totalDataCount * 8) {
      break;
    }
    buffer.put(QRCode.PAD1, 8);
  }

  return QRCode.createBytes(buffer, rsBlocks);
}

QRCode.createBytes = function(buffer, rsBlocks) {

  var offset = 0;

  var maxDcCount = 0;
  var maxEcCount = 0;

  var dcdata = new Array(rsBlocks.length);
  var ecdata = new Array(rsBlocks.length);

  for (var r = 0; r < rsBlocks.length; r++) {

    var dcCount = rsBlocks[r].dataCount;
    var ecCount = rsBlocks[r].totalCount - dcCount;

    maxDcCount = Math.max(maxDcCount, dcCount);
    maxEcCount = Math.max(maxEcCount, ecCount);

    dcdata[r] = new Array(dcCount);

    for (var i = 0; i < dcdata[r].length; i++) {
      dcdata[r][i] = 0xff & buffer.buffer[i + offset];
    }
    offset += dcCount;

    var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
    var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);

    var modPoly = rawPoly.mod(rsPoly);
    ecdata[r] = new Array(rsPoly.getLength() - 1);
    for (var i = 0; i < ecdata[r].length; i++) {
      var modIndex = i + modPoly.getLength() - ecdata[r].length;
      ecdata[r][i] = (modIndex >= 0)? modPoly.get(modIndex) : 0;
    }

  }

  var totalCodeCount = 0;
  for (var i = 0; i < rsBlocks.length; i++) {
    totalCodeCount += rsBlocks[i].totalCount;
  }

  var data = new Array(totalCodeCount);
  var index = 0;

  for (var i = 0; i < maxDcCount; i++) {
    for (var r = 0; r < rsBlocks.length; r++) {
      if (i < dcdata[r].length) {
        data[index++] = dcdata[r][i];
      }
    }
  }

  for (var i = 0; i < maxEcCount; i++) {
    for (var r = 0; r < rsBlocks.length; r++) {
      if (i < ecdata[r].length) {
        data[index++] = ecdata[r][i];
      }
    }
  }

  return data;

}

//---------------------------------------------------------------------
// QRMode
//---------------------------------------------------------------------

var QRMode = {
  MODE_NUMBER :		1 << 0,
  MODE_ALPHA_NUM : 	1 << 1,
  MODE_8BIT_BYTE : 	1 << 2,
  MODE_KANJI :		1 << 3
};

//---------------------------------------------------------------------
// QRErrorCorrectLevel
//---------------------------------------------------------------------

var QRErrorCorrectLevel = {
  L : 1,
  M : 0,
  Q : 3,
  H : 2
};

//---------------------------------------------------------------------
// QRMaskPattern
//---------------------------------------------------------------------

var QRMaskPattern = {
  PATTERN000 : 0,
  PATTERN001 : 1,
  PATTERN010 : 2,
  PATTERN011 : 3,
  PATTERN100 : 4,
  PATTERN101 : 5,
  PATTERN110 : 6,
  PATTERN111 : 7
};

//---------------------------------------------------------------------
// QRUtil
//---------------------------------------------------------------------

var QRUtil = {

  PATTERN_POSITION_TABLE : [
    [],
    [6, 18],
    [6, 22],
    [6, 26],
    [6, 30],
    [6, 34],
    [6, 22, 38],
    [6, 24, 42],
    [6, 26, 46],
    [6, 28, 50],
    [6, 30, 54],
    [6, 32, 58],
    [6, 34, 62],
    [6, 26, 46, 66],
    [6, 26, 48, 70],
    [6, 26, 50, 74],
    [6, 30, 54, 78],
    [6, 30, 56, 82],
    [6, 30, 58, 86],
    [6, 34, 62, 90],
    [6, 28, 50, 72, 94],
    [6, 26, 50, 74, 98],
    [6, 30, 54, 78, 102],
    [6, 28, 54, 80, 106],
    [6, 32, 58, 84, 110],
    [6, 30, 58, 86, 114],
    [6, 34, 62, 90, 118],
    [6, 26, 50, 74, 98, 122],
    [6, 30, 54, 78, 102, 126],
    [6, 26, 52, 78, 104, 130],
    [6, 30, 56, 82, 108, 134],
    [6, 34, 60, 86, 112, 138],
    [6, 30, 58, 86, 114, 142],
    [6, 34, 62, 90, 118, 146],
    [6, 30, 54, 78, 102, 126, 150],
    [6, 24, 50, 76, 102, 128, 154],
    [6, 28, 54, 80, 106, 132, 158],
    [6, 32, 58, 84, 110, 136, 162],
    [6, 26, 54, 82, 110, 138, 166],
    [6, 30, 58, 86, 114, 142, 170]
  ],

  G15 : (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
  G18 : (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
  G15_MASK : (1 << 14) | (1 << 12) | (1 << 10)	| (1 << 4) | (1 << 1),

  getBCHTypeInfo : function(data) {
    var d = data << 10;
    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
      d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) );
    }
    return ( (data << 10) | d) ^ QRUtil.G15_MASK;
  },

  getBCHTypeNumber : function(data) {
    var d = data << 12;
    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
      d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) );
    }
    return (data << 12) | d;
  },

  getBCHDigit : function(data) {

    var digit = 0;

    while (data != 0) {
      digit++;
      data >>>= 1;
    }

    return digit;
  },

  getPatternPosition : function(typeNumber) {
    return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
  },

  getMask : function(maskPattern, i, j) {

    switch (maskPattern) {

      case QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0;
      case QRMaskPattern.PATTERN001 : return i % 2 == 0;
      case QRMaskPattern.PATTERN010 : return j % 3 == 0;
      case QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0;
      case QRMaskPattern.PATTERN100 : return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0;
      case QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0;
      case QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0;
      case QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0;

      default :
        throw new Error("bad maskPattern:" + maskPattern);
    }
  },

  getErrorCorrectPolynomial : function(errorCorrectLength) {

    var a = new QRPolynomial([1], 0);

    for (var i = 0; i < errorCorrectLength; i++) {
      a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0) );
    }

    return a;
  },

  getLengthInBits : function(mode, type) {

    if (1 <= type && type < 10) {

      // 1 - 9

      switch(mode) {
        case QRMode.MODE_NUMBER 	: return 10;
        case QRMode.MODE_ALPHA_NUM 	: return 9;
        case QRMode.MODE_8BIT_BYTE	: return 8;
        case QRMode.MODE_KANJI  	: return 8;
        default :
          throw new Error("mode:" + mode);
      }

    } else if (type < 27) {

      // 10 - 26

      switch(mode) {
        case QRMode.MODE_NUMBER 	: return 12;
        case QRMode.MODE_ALPHA_NUM 	: return 11;
        case QRMode.MODE_8BIT_BYTE	: return 16;
        case QRMode.MODE_KANJI  	: return 10;
        default :
          throw new Error("mode:" + mode);
      }

    } else if (type < 41) {

      // 27 - 40

      switch(mode) {
        case QRMode.MODE_NUMBER 	: return 14;
        case QRMode.MODE_ALPHA_NUM	: return 13;
        case QRMode.MODE_8BIT_BYTE	: return 16;
        case QRMode.MODE_KANJI  	: return 12;
        default :
          throw new Error("mode:" + mode);
      }

    } else {
      throw new Error("type:" + type);
    }
  },

  getLostPoint : function(qrCode) {

    var moduleCount = qrCode.getModuleCount();

    var lostPoint = 0;

    // LEVEL1

    for (var row = 0; row < moduleCount; row++) {

      for (var col = 0; col < moduleCount; col++) {

        var sameCount = 0;
        var dark = qrCode.isDark(row, col);

        for (var r = -1; r <= 1; r++) {

          if (row + r < 0 || moduleCount <= row + r) {
            continue;
          }

          for (var c = -1; c <= 1; c++) {

            if (col + c < 0 || moduleCount <= col + c) {
              continue;
            }

            if (r == 0 && c == 0) {
              continue;
            }

            if (dark == qrCode.isDark(row + r, col + c) ) {
              sameCount++;
            }
          }
        }

        if (sameCount > 5) {
          lostPoint += (3 + sameCount - 5);
        }
      }
    }

    // LEVEL2

    for (var row = 0; row < moduleCount - 1; row++) {
      for (var col = 0; col < moduleCount - 1; col++) {
        var count = 0;
        if (qrCode.isDark(row,     col    ) ) count++;
        if (qrCode.isDark(row + 1, col    ) ) count++;
        if (qrCode.isDark(row,     col + 1) ) count++;
        if (qrCode.isDark(row + 1, col + 1) ) count++;
        if (count == 0 || count == 4) {
          lostPoint += 3;
        }
      }
    }

    // LEVEL3

    for (var row = 0; row < moduleCount; row++) {
      for (var col = 0; col < moduleCount - 6; col++) {
        if (qrCode.isDark(row, col)
          && !qrCode.isDark(row, col + 1)
          &&  qrCode.isDark(row, col + 2)
          &&  qrCode.isDark(row, col + 3)
          &&  qrCode.isDark(row, col + 4)
          && !qrCode.isDark(row, col + 5)
          &&  qrCode.isDark(row, col + 6) ) {
          lostPoint += 40;
        }
      }
    }

    for (var col = 0; col < moduleCount; col++) {
      for (var row = 0; row < moduleCount - 6; row++) {
        if (qrCode.isDark(row, col)
          && !qrCode.isDark(row + 1, col)
          &&  qrCode.isDark(row + 2, col)
          &&  qrCode.isDark(row + 3, col)
          &&  qrCode.isDark(row + 4, col)
          && !qrCode.isDark(row + 5, col)
          &&  qrCode.isDark(row + 6, col) ) {
          lostPoint += 40;
        }
      }
    }

    // LEVEL4

    var darkCount = 0;

    for (var col = 0; col < moduleCount; col++) {
      for (var row = 0; row < moduleCount; row++) {
        if (qrCode.isDark(row, col) ) {
          darkCount++;
        }
      }
    }

    var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
    lostPoint += ratio * 10;

    return lostPoint;
  }

};


//---------------------------------------------------------------------
// QRMath
//---------------------------------------------------------------------

var QRMath = {

  glog : function(n) {

    if (n < 1) {
      throw new Error("glog(" + n + ")");
    }

    return QRMath.LOG_TABLE[n];
  },

  gexp : function(n) {

    while (n < 0) {
      n += 255;
    }

    while (n >= 256) {
      n -= 255;
    }

    return QRMath.EXP_TABLE[n];
  },

  EXP_TABLE : new Array(256),

  LOG_TABLE : new Array(256)

};

for (var i = 0; i < 8; i++) {
  QRMath.EXP_TABLE[i] = 1 << i;
}
for (var i = 8; i < 256; i++) {
  QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4]
    ^ QRMath.EXP_TABLE[i - 5]
    ^ QRMath.EXP_TABLE[i - 6]
    ^ QRMath.EXP_TABLE[i - 8];
}
for (var i = 0; i < 255; i++) {
  QRMath.LOG_TABLE[QRMath.EXP_TABLE[i] ] = i;
}

//---------------------------------------------------------------------
// QRPolynomial
//---------------------------------------------------------------------

function QRPolynomial(num, shift) {

  if (num.length == undefined) {
    throw new Error(num.length + "/" + shift);
  }

  var offset = 0;

  while (offset < num.length && num[offset] == 0) {
    offset++;
  }

  this.num = new Array(num.length - offset + shift);
  for (var i = 0; i < num.length - offset; i++) {
    this.num[i] = num[i + offset];
  }
}

QRPolynomial.prototype = {

  get : function(index) {
    return this.num[index];
  },

  getLength : function() {
    return this.num.length;
  },

  multiply : function(e) {

    var num = new Array(this.getLength() + e.getLength() - 1);

    for (var i = 0; i < this.getLength(); i++) {
      for (var j = 0; j < e.getLength(); j++) {
        num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i) ) + QRMath.glog(e.get(j) ) );
      }
    }

    return new QRPolynomial(num, 0);
  },

  mod : function(e) {

    if (this.getLength() - e.getLength() < 0) {
      return this;
    }

    var ratio = QRMath.glog(this.get(0) ) - QRMath.glog(e.get(0) );

    var num = new Array(this.getLength() );

    for (var i = 0; i < this.getLength(); i++) {
      num[i] = this.get(i);
    }

    for (var i = 0; i < e.getLength(); i++) {
      num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio);
    }

    // recursive call
    return new QRPolynomial(num, 0).mod(e);
  }
};

//---------------------------------------------------------------------
// QRRSBlock
//---------------------------------------------------------------------

function QRRSBlock(totalCount, dataCount) {
  this.totalCount = totalCount;
  this.dataCount  = dataCount;
}

QRRSBlock.RS_BLOCK_TABLE = [

  // L
  // M
  // Q
  // H

  // 1
  [1, 26, 19],
  [1, 26, 16],
  [1, 26, 13],
  [1, 26, 9],

  // 2
  [1, 44, 34],
  [1, 44, 28],
  [1, 44, 22],
  [1, 44, 16],

  // 3
  [1, 70, 55],
  [1, 70, 44],
  [2, 35, 17],
  [2, 35, 13],

  // 4
  [1, 100, 80],
  [2, 50, 32],
  [2, 50, 24],
  [4, 25, 9],

  // 5
  [1, 134, 108],
  [2, 67, 43],
  [2, 33, 15, 2, 34, 16],
  [2, 33, 11, 2, 34, 12],

  // 6
  [2, 86, 68],
  [4, 43, 27],
  [4, 43, 19],
  [4, 43, 15],

  // 7
  [2, 98, 78],
  [4, 49, 31],
  [2, 32, 14, 4, 33, 15],
  [4, 39, 13, 1, 40, 14],

  // 8
  [2, 121, 97],
  [2, 60, 38, 2, 61, 39],
  [4, 40, 18, 2, 41, 19],
  [4, 40, 14, 2, 41, 15],

  // 9
  [2, 146, 116],
  [3, 58, 36, 2, 59, 37],
  [4, 36, 16, 4, 37, 17],
  [4, 36, 12, 4, 37, 13],

  // 10
  [2, 86, 68, 2, 87, 69],
  [4, 69, 43, 1, 70, 44],
  [6, 43, 19, 2, 44, 20],
  [6, 43, 15, 2, 44, 16],

  // 11
  [4, 101, 81],
  [1, 80, 50, 4, 81, 51],
  [4, 50, 22, 4, 51, 23],
  [3, 36, 12, 8, 37, 13],

  // 12
  [2, 116, 92, 2, 117, 93],
  [6, 58, 36, 2, 59, 37],
  [4, 46, 20, 6, 47, 21],
  [7, 42, 14, 4, 43, 15],

  // 13
  [4, 133, 107],
  [8, 59, 37, 1, 60, 38],
  [8, 44, 20, 4, 45, 21],
  [12, 33, 11, 4, 34, 12],

  // 14
  [3, 145, 115, 1, 146, 116],
  [4, 64, 40, 5, 65, 41],
  [11, 36, 16, 5, 37, 17],
  [11, 36, 12, 5, 37, 13],

  // 15
  [5, 109, 87, 1, 110, 88],
  [5, 65, 41, 5, 66, 42],
  [5, 54, 24, 7, 55, 25],
  [11, 36, 12],

  // 16
  [5, 122, 98, 1, 123, 99],
  [7, 73, 45, 3, 74, 46],
  [15, 43, 19, 2, 44, 20],
  [3, 45, 15, 13, 46, 16],

  // 17
  [1, 135, 107, 5, 136, 108],
  [10, 74, 46, 1, 75, 47],
  [1, 50, 22, 15, 51, 23],
  [2, 42, 14, 17, 43, 15],

  // 18
  [5, 150, 120, 1, 151, 121],
  [9, 69, 43, 4, 70, 44],
  [17, 50, 22, 1, 51, 23],
  [2, 42, 14, 19, 43, 15],

  // 19
  [3, 141, 113, 4, 142, 114],
  [3, 70, 44, 11, 71, 45],
  [17, 47, 21, 4, 48, 22],
  [9, 39, 13, 16, 40, 14],

  // 20
  [3, 135, 107, 5, 136, 108],
  [3, 67, 41, 13, 68, 42],
  [15, 54, 24, 5, 55, 25],
  [15, 43, 15, 10, 44, 16],

  // 21
  [4, 144, 116, 4, 145, 117],
  [17, 68, 42],
  [17, 50, 22, 6, 51, 23],
  [19, 46, 16, 6, 47, 17],

  // 22
  [2, 139, 111, 7, 140, 112],
  [17, 74, 46],
  [7, 54, 24, 16, 55, 25],
  [34, 37, 13],

  // 23
  [4, 151, 121, 5, 152, 122],
  [4, 75, 47, 14, 76, 48],
  [11, 54, 24, 14, 55, 25],
  [16, 45, 15, 14, 46, 16],

  // 24
  [6, 147, 117, 4, 148, 118],
  [6, 73, 45, 14, 74, 46],
  [11, 54, 24, 16, 55, 25],
  [30, 46, 16, 2, 47, 17],

  // 25
  [8, 132, 106, 4, 133, 107],
  [8, 75, 47, 13, 76, 48],
  [7, 54, 24, 22, 55, 25],
  [22, 45, 15, 13, 46, 16],

  // 26
  [10, 142, 114, 2, 143, 115],
  [19, 74, 46, 4, 75, 47],
  [28, 50, 22, 6, 51, 23],
  [33, 46, 16, 4, 47, 17],

  // 27
  [8, 152, 122, 4, 153, 123],
  [22, 73, 45, 3, 74, 46],
  [8, 53, 23, 26, 54, 24],
  [12, 45, 15, 28, 46, 16],

  // 28
  [3, 147, 117, 10, 148, 118],
  [3, 73, 45, 23, 74, 46],
  [4, 54, 24, 31, 55, 25],
  [11, 45, 15, 31, 46, 16],

  // 29
  [7, 146, 116, 7, 147, 117],
  [21, 73, 45, 7, 74, 46],
  [1, 53, 23, 37, 54, 24],
  [19, 45, 15, 26, 46, 16],

  // 30
  [5, 145, 115, 10, 146, 116],
  [19, 75, 47, 10, 76, 48],
  [15, 54, 24, 25, 55, 25],
  [23, 45, 15, 25, 46, 16],

  // 31
  [13, 145, 115, 3, 146, 116],
  [2, 74, 46, 29, 75, 47],
  [42, 54, 24, 1, 55, 25],
  [23, 45, 15, 28, 46, 16],

  // 32
  [17, 145, 115],
  [10, 74, 46, 23, 75, 47],
  [10, 54, 24, 35, 55, 25],
  [19, 45, 15, 35, 46, 16],

  // 33
  [17, 145, 115, 1, 146, 116],
  [14, 74, 46, 21, 75, 47],
  [29, 54, 24, 19, 55, 25],
  [11, 45, 15, 46, 46, 16],

  // 34
  [13, 145, 115, 6, 146, 116],
  [14, 74, 46, 23, 75, 47],
  [44, 54, 24, 7, 55, 25],
  [59, 46, 16, 1, 47, 17],

  // 35
  [12, 151, 121, 7, 152, 122],
  [12, 75, 47, 26, 76, 48],
  [39, 54, 24, 14, 55, 25],
  [22, 45, 15, 41, 46, 16],

  // 36
  [6, 151, 121, 14, 152, 122],
  [6, 75, 47, 34, 76, 48],
  [46, 54, 24, 10, 55, 25],
  [2, 45, 15, 64, 46, 16],

  // 37
  [17, 152, 122, 4, 153, 123],
  [29, 74, 46, 14, 75, 47],
  [49, 54, 24, 10, 55, 25],
  [24, 45, 15, 46, 46, 16],

  // 38
  [4, 152, 122, 18, 153, 123],
  [13, 74, 46, 32, 75, 47],
  [48, 54, 24, 14, 55, 25],
  [42, 45, 15, 32, 46, 16],

  // 39
  [20, 147, 117, 4, 148, 118],
  [40, 75, 47, 7, 76, 48],
  [43, 54, 24, 22, 55, 25],
  [10, 45, 15, 67, 46, 16],

  // 40
  [19, 148, 118, 6, 149, 119],
  [18, 75, 47, 31, 76, 48],
  [34, 54, 24, 34, 55, 25],
  [20, 45, 15, 61, 46, 16]
];

QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) {

  var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);

  if (rsBlock == undefined) {
    throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
  }

  var length = rsBlock.length / 3;

  var list = new Array();

  for (var i = 0; i < length; i++) {

    var count = rsBlock[i * 3 + 0];
    var totalCount = rsBlock[i * 3 + 1];
    var dataCount  = rsBlock[i * 3 + 2];

    for (var j = 0; j < count; j++) {
      list.push(new QRRSBlock(totalCount, dataCount) );
    }
  }

  return list;
}

QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) {

  switch(errorCorrectLevel) {
    case QRErrorCorrectLevel.L :
      return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
    case QRErrorCorrectLevel.M :
      return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
    case QRErrorCorrectLevel.Q :
      return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
    case QRErrorCorrectLevel.H :
      return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
    default :
      return undefined;
  }
}

//---------------------------------------------------------------------
// QRBitBuffer
//---------------------------------------------------------------------

function QRBitBuffer() {
  this.buffer = new Array();
  this.length = 0;
}

QRBitBuffer.prototype = {

  get : function(index) {
    var bufIndex = Math.floor(index / 8);
    return ( (this.buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
  },

  put : function(num, length) {
    for (var i = 0; i < length; i++) {
      this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
    }
  },

  getLengthInBits : function() {
    return this.length;
  },

  putBit : function(bit) {

    var bufIndex = Math.floor(this.length / 8);
    if (this.buffer.length <= bufIndex) {
      this.buffer.push(0);
    }

    if (bit) {
      this.buffer[bufIndex] |= (0x80 >>> (this.length % 8) );
    }

    this.length++;
  }
};


/**
 * jQuery Qrcode
 */
(function( $ ){
  $.fn.qrcode = function(options) {
    // if options is string,
    if( typeof options === 'string' ){
      options	= { text: options };
    }

    // set default values
    // typeNumber < 1 for automatic calculation
    options	= $.extend( {}, {
      render		: "canvas",
      width		: 256,
      height		: 256,
      typeNumber	: -1,
      correctLevel	: QRErrorCorrectLevel.H,
      background      : "#ffffff",
      foreground      : "#000000"
    }, options);

    var createCanvas	= function(){
      // create the qrcode itself
      var qrcode	= new QRCode(options.typeNumber, options.correctLevel);
      qrcode.addData(options.text);
      qrcode.make();

      // create canvas element
      var canvas	= document.createElement('canvas');
      canvas.width	= options.width;
      canvas.height	= options.height;
      var ctx		= canvas.getContext('2d');

      // compute tileW/tileH based on options.width/options.height
      var tileW	= options.width  / qrcode.getModuleCount();
      var tileH	= options.height / qrcode.getModuleCount();

      // draw in the canvas
      for( var row = 0; row < qrcode.getModuleCount(); row++ ){
        for( var col = 0; col < qrcode.getModuleCount(); col++ ){
          ctx.fillStyle = qrcode.isDark(row, col) ? options.foreground : options.background;
          var w = (Math.ceil((col+1)*tileW) - Math.floor(col*tileW));
          var h = (Math.ceil((row+1)*tileH) - Math.floor(row*tileH));
          ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH), w, h);
        }
      }
      // return just built canvas
      return canvas;
    }

    // from Jon-Carlos Rivera (https://github.com/imbcmdth)
    var createTable	= function(){
      // create the qrcode itself
      var qrcode	= new QRCode(options.typeNumber, options.correctLevel);
      qrcode.addData(options.text);
      qrcode.make();

      // create table element
      var $table	= $('<table></table>')
        .css("width", options.width+"px")
        .css("height", options.height+"px")
        .css("border", "0px")
        .css("border-collapse", "collapse")
        .css('background-color', options.background);

      // compute tileS percentage
      var tileW	= options.width / qrcode.getModuleCount();
      var tileH	= options.height / qrcode.getModuleCount();

      // draw in the table
      for(var row = 0; row < qrcode.getModuleCount(); row++ ){
        var $row = $('<tr></tr>').css('height', tileH+"px").appendTo($table);

        for(var col = 0; col < qrcode.getModuleCount(); col++ ){
          $('<td></td>')
            .css('width', tileW+"px")
            .css('background-color', qrcode.isDark(row, col) ? options.foreground : options.background)
            .appendTo($row);
        }
      }
      // return just built canvas
      return $table;
    }


    return this.each(function(){
      var element	= options.render == "canvas" ? createCanvas() : createTable();
      $(element).appendTo(this);
    });
  };
})( jQuery );


